﻿using System.Collections.Generic;
using System.Text;
using swe.Core;

namespace CsvParser
{
	public class CsvParserStateMachine
	{
		public static IEnumerable<string> SplitLine(string line)
		{
			var str = line;
			var data = new StringBuilder();
			var wf = StateMachine<int, string>.Create("Item")
				.State("Item", (s, i) =>
								{
									if (i >= str.Length)
									{
										s.Return(data.ToString());
										return StateMachine.Break;
									}
									if (str[i] == ',')
									{
										s.UpdateObject(i + 1);
										s.Return(data.ToString());
										data = new StringBuilder();
										return StateMachine.Loop;
									}
									if (str[i] == '"')
									{
										s.UpdateObject(i + 1);
										return StateMachine.NamedState("QItem");
									}
									if (str[i] == '\\')
									{
										s.UpdateObject(i + 2);
										data.Append('"');
										return StateMachine.Loop;
									}
									s.UpdateObject(i + 1);
									data.Append(str[i]);
									return StateMachine.Loop;
								}
				)
				.State("QItem", (s, i) =>
				                	{
										if (i >= str.Length)
										{
											s.Return(data.ToString());
											data.Clear();
											return StateMachine.Break;
										}
										if (str[i] == '"')
										{
											s.UpdateObject(i + 1);
											s.Return(data.ToString());
											data.Clear();
											return StateMachine.NamedState("Trans");
										}
										if (str[i] == '\\')
										{
											s.UpdateObject(i + 2);
											data.Append('"');
											return StateMachine.Loop;
										}
										s.UpdateObject(i + 1);
										data.Append(str[i]);
										return StateMachine.Loop;
				                	})
				.State("Trans", (s, i) =>
				                	{
										if (i>=str.Length)
											return StateMachine.Break;
										if (str[i] == ',')
										{
											s.UpdateObject(i + 1);
											return StateMachine.NamedState("Item");
										}
										s.UpdateObject(i + 1);
				                		return StateMachine.Loop;
				                	}, StateType.Transfer);
				

			var sm = (IStableStateMachine<string>)wf.BindTo(0);
			while (!sm.Eos)
			{
				sm.ProcessToStableState();
				if (sm.HasReturn)
				{
					yield return sm.GetRturnData();
				}
			}
		}
	}
}
